// Copyright 2023 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef CPH_VIDEO_PARAMS_H
#define CPH_VIDEO_PARAMS_H

#include <stdint.h>
#include <arpa/inet.h>

enum EncodeType {
    ENCODER_TYPE_DEFAULT = 0,
    ENCODER_TYPE_CPU,
    ENCODER_TYPE_GPU,            // 用户指定硬编
    ENCODER_TYPE_D310,
    ENCODER_TYPE_LOCAL_CPU,
    ENCODER_TYPE_LOCAL_T432,
    ENCODER_TYPE_LOCAL_P2,
    ENCODER_TYPE_REMOTE_HOST_CPU,
    ENCODER_TYPE_REMOTE_HOST_GPU,
    ENCODER_TYPE_INVALID
};

enum EncodeFrameType {
    FRAME_TYPE_H264 = 0,
    FRAME_TYPE_H265,
    FRAME_TYPE_ENCODER_MAX
};

enum EncodeConfErr {
    NO_ERR = 0,
    ENCODER_TYPE_ERR,
    VIDEO_FRAME_TYPE_ERR,
    RESOLUTION_ERR,
    FRAMERATE_ERR
};

enum TLV_TYPE {
    TLV_TYPE_NONE = 0,
    TLV_TYPE_START_CAP_TS,
    TLV_TYPE_END_CAP_TS,
    TLV_TYPE_START_ENCODE_TS,
    TLV_TYPE_END_ENCODE_TS,
    TLV_TYPE_STREAM,
    TLV_TYPE_YUV
};

struct TLVPacket {
    uint8_t tlvType;
    uint32_t tlvLength;
    uint8_t* tlvData;
}__attribute__((packed));

// 返回错误码
#ifndef VMI_SUCCESS
#define VMI_SUCCESS                       0
#endif
#define VMI_VIDEO_ENGINE_INIT_FAIL        0x0A080001 // 视频引擎服务端初始化失败
#define VMI_VIDEO_ENGINE_ERR              0x0A080002 // 视频引擎服务端运行出错
#define VMI_VIDEO_ENGINE_PARAM_INVALID    0x0A080003 // 视频引擎服务端参数无效
#define VMI_VIDEO_ENGINE_PARAM_UNSUPORTED 0x0A080004 // 视频引擎服务端参数不支持
#define VMI_VIDEO_ENGINE_START_ERR        0x0A080005 // 视频引擎服务端启动失败
#define VMI_VIDEO_ENGINE_CONFIG_ERR       0x0A080005 // 视频引擎服务端配置出错
#define VMI_VIDEO_ENGINE_REGISTER_ERR     0x0A080006 // 视频引擎服务端注册出错
#define VMI_VIDEO_ENGINE_GET_STAT_ERR     0x0A080007 // 视频引擎服务端获取统计信息失败
#define VMI_VIDEO_ENGINE_ENCODE_ERR       0x0A080008 // 视频引擎服务端处理数据失败
#define VMI_VIDEO_ENGINE_STOP_ERR         0x0A080009 // 视频引擎服务端停止过程出现错误
#define VMI_VIDEO_ENGINE_DESTROY_ERR      0x0A08000A // 视频引擎服务端销毁过程出现错误

#define FRAME_FLAG_ISNOTYUV  (1)  // 1 << 0
#define FRAME_FLAG_NEEDFREE  (2)  // 1 << 1
#define FRAME_FLAG_ISIFRAME  (4)  // 1 << 2
#define FRAME_FLAG_HAS_ORIENTATION  (8)  // 1 << 3

static inline bool isBigEndian() {
    uint16_t flag = 0xFF;
    uint8_t *pFirst = reinterpret_cast<uint8_t *>(&flag);
    return *pFirst == 0;
}

#define swap64(val) (((val) >> 56) |\
                    (((val) & 0x00ff000000000000ll) >> 40) |\
                    (((val) & 0x0000ff0000000000ll) >> 24) |\
                    (((val) & 0x000000ff00000000ll) >> 8)   |\
                    (((val) & 0x00000000ff000000ll) << 8)   |\
                    (((val) & 0x0000000000ff0000ll) << 24) |\
                    (((val) & 0x000000000000ff00ll) << 40) |\
                    (((val) << 56)))

#define hton64(val) (isBigEndian() ? val : swap64(val))
#define ntoh64(val) hton64(val)

// 编码参数
struct EncoderParam {
    uint32_t frameRate; // 帧率0~60
    uint32_t bitrate;   // 100k~10M
    uint32_t gopSize;   // I帧间隔30~5000
    uint32_t profile;   // 66,77,100
    uint32_t width;     // 32对齐
    uint32_t height;    // 4对齐
    EncodeFrameType frameType = FRAME_TYPE_H264;
};

struct VideoParamExt {
    uint64_t startCaptureTs;  // 抓图一帧开始时间戳
    uint64_t endCaptureTs;  // 抓图一帧结束时间戳
    uint64_t startEncodeTs;  // 编码一帧开始时间戳
    uint64_t endEncodeTs ;  // 编码一帧结束时间戳

    uint8_t *frame_data;
    uint8_t frame_flag;
    uint8_t orientation;
    uint16_t reserved_2_bytes;
    uint32_t frame_stride;
    uint32_t frame_width;
    uint32_t frame_height;
    uint64_t frame_number;
    uint64_t pts_number;
};

// 视频数据的时间戳信息 作为报文内容与远端编码器通信
struct VideoParamExtMsg {
    uint64_t startCaptureTs {0xFFFFFFFFFFFFFFFF};  // 抓图一帧开始时间戳
    uint64_t endCaptureTs {0xFFFFFFFFFFFFFFFF};  // 抓图一帧结束时间戳
    uint64_t startEncodeTs {0xFFFFFFFFFFFFFFFF};  // 编码一帧开始时间戳
    uint64_t endEncodeTs {0xFFFFFFFFFFFFFFFF};  // 编码一帧结束时间戳

    void netToHostOrder() {
        startCaptureTs = ntoh64(startCaptureTs);
        endCaptureTs = ntoh64(endCaptureTs);
        startEncodeTs = ntoh64(startEncodeTs);
        endEncodeTs = ntoh64(endEncodeTs);
    }
};

// 引擎状态
enum EngineStat {
    VMI_ENCODE_ENGINE_INIT = 1,
    VMI_ENCODE_ENGINE_RUNNING,
    VMI_ENCODE_ENGINE_STOP,
    VMI_ENCODE_ENGINE_EXIT,
    VMI_ENCODE_ENGINE_INVALID
};

// 统计信息
struct EncoderStatistics {
    uint32_t encodeFps; // 实时编码帧率
    uint32_t bitrate;   // 实时码率
};

using VIDEOCALLBACK = int(*)(uint8_t *data, int length, VideoParamExt &param);

#endif //CPH_VIDEO_PARAMS_H